package com.xiyoufang.mycli.tunnel;

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jfinal.kit.StrKit;
import com.jfinal.template.Engine;
import com.xiyoufang.mycli.Config;
import com.xiyoufang.mycli.Utils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import picocli.CommandLine;

import java.io.File;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Callable;

/**
 * Created by 席有芳 on 2021/11/26.
 *
 * @author 席有芳
 */
public abstract class Connected implements Callable<Integer> {
    /**
     * 环境变量
     */
    protected final Properties env = new Properties();

    /**
     * 帮助信息
     */
    @CommandLine.Option(names = {"-h", "--help"}, usageHelp = true)
    private boolean help;
    /**
     * 名称
     */
    @CommandLine.Option(names = {"-n", "--name"}, defaultValue = "", description = "配置名称: 对应一个服务器, 例如: www")
    private String name;
    /**
     * 原始端口
     */
    @CommandLine.Option(names = {"-f", "--from"}, description = "原始端口, 例如: 8888", required = true)
    protected List<Integer> froms;
    /**
     * 目标端口
     */
    @CommandLine.Option(names = {"-t", "--to"}, description = "目标端口, 例如: 8888", required = true)
    protected List<Integer> tos;
    /**
     * session
     */
    protected Session session;

    @Override
    public Integer call() throws Exception {
        File envFile = Utils.getEnv(Init.ENV, name);
        if (!envFile.exists()) {
            System.out.println("<" + envFile.getName() + "> 文件不存在, 请先使用my-cli tunnel init 初始化.");
            return -1;
        }
        String content = Engine.use().getTemplateByString(FileUtils.readFileToString(envFile, Config.DEFAULT_CHARSET)).renderToString(System.getenv());
        try (InputStream in = IOUtils.toInputStream(content, Config.DEFAULT_CHARSET)) {
            env.load(in);
        }
        String host = env.getProperty("host");
        int port = Integer.parseInt(env.getProperty("port"));
        String username = env.getProperty("username");
        String key = env.getProperty("key");
        String password = env.getProperty("password");
        int timeout = Integer.parseInt(env.getProperty("timeout"));
        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        JSch jsch = new JSch();
        if (StrKit.notBlank(key)) jsch.addIdentity(host, key.getBytes(), null, password.getBytes());
        session = jsch.getSession(username, host, port);
        if (StrKit.isBlank(key)) session.setPassword(password);
        session.setConfig(config);
        session.connect(timeout * 1000);
        return doCall();
    }

    /**
     * 等待掉线
     */
    protected void waitDisconnect() {
        while (session.isConnected()) Utils.sleep(2 * 1000);
        System.err.println("连接已中断");
    }

    /**
     * 执行
     *
     * @return int
     */
    protected abstract Integer doCall() throws Exception;
}
